﻿using Common;
using IP20.Procdure;
using LiveCharts;
using NewDevice;
using NewDevice.RS232;
using NewDevice.RS485;
using NewDevice.USB;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Finance.Implementations;
using OfficeOpenXml.ThreadedComments;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using NewDevice.XiWei;
using TwinCAT.Ads;
using System.Linq.Expressions;
using System.Windows.Shapes;
using Path = System.IO.Path;

namespace IP20.ViewModel
{
    internal class HomeViewModel : NotifyBase
    {
        private int logIndex = 1;

        private static List<string> SearchFiles(string directoryPath, string searchPattern)
        {
            List<string> foundFiles = new List<string>();

            // 检查目录是否存在
            if (!Directory.Exists(directoryPath))
            {
                throw new DirectoryNotFoundException($"目录不存在：{directoryPath}");
            }

            // 获取目录下所有文件
            string[] allFiles = Directory.GetFiles(directoryPath, "*", SearchOption.TopDirectoryOnly);

            // 筛选包含指定字符串的文件
            foreach (string file in allFiles)
            {
                string fileName = Path.GetFileName(file);
                if (fileName.StartsWith(searchPattern))
                {
                    foundFiles.Add(Path.GetFullPath(file));
                }
            }

            return foundFiles;
        }

        private bool? _isWriteFlash;

        public bool? IsWriteFlash
        {
            get { return _isWriteFlash; }
            set
            {
                _isWriteFlash = value;
                this.DoNotify();
#if JQ8931314
                try
                {
                    LoadTestConfig();
                }
                catch (Exception ex)
                {
                    Log = $"{ex.Message}!";
                }
#endif
            }
        }

        private string _log;

        public string Log
        {
            get { return _log; }
            set
            {
                Application.Current.Dispatcher.Invoke(new Action(() =>
                {
                    _log = $"[{logIndex++.ToString()}] {value}";
                    this.DoNotify();
                    Mylog.Info(_log);
                }));
            }
        }

        private string _testConfigFilePath;

        public string TestConfigFilePath
        {
            get { return _testConfigFilePath; }
            set
            {
                _testConfigFilePath = value;
                this.DoNotify();
            }
        }

        private string _sn1;

        public string SN1
        {
            get { return _sn1; }
            set
            {
                _sn1 = value;
                this.DoNotify();
                if (value.Length >= snLength)
                {
                    if (Station2Checked)
                    {
                        SNInputAction.Invoke(2);
                    }
                }
            }
        }

        private string _sn2;

        public string SN2
        {
            get { return _sn2; }
            set
            {
                _sn2 = value;
                this.DoNotify();
            }
        }

        //OnlyViewTestEnable
        private bool _onlyViewTestEnable;

        public bool OnlyViewTestEnable
        {
            get { return _onlyViewTestEnable; }
            set
            {
                _onlyViewTestEnable = value;
                this.DoNotify();
            }
        }

        private int _okCount;

        public int OKCount
        {
            get { return _okCount; }
            set
            {
                _okCount = value;
                this.DoNotify();
                Counter.OkCount = value;
                Counter.Save(Counter);
            }
        }

        private int _ngCount;

        public int NGCount
        {
            get { return _ngCount; }
            set
            {
                _ngCount = value;
                this.DoNotify();
                Counter.NgCount = value;
                Counter.Save(Counter);
            }
        }

        private bool? _result;

        public bool? Result
        {
            get { return _result; }
            set
            {
                _result = value;
                this.DoNotify();
            }
        }

        private bool? _result2;

        public bool? Result2
        {
            get { return _result2; }
            set
            {
                _result2 = value;
                this.DoNotify();
            }
        }

        public Counter Counter { get; set; }
        public Func<ChartPoint, string> PointLabel { get; set; }

        public ObservableCollection<TestItem> Data { get; set; }
        public ObservableCollection<TestItem> Data2 { get; set; }

        private TestItem _selectedItem;

        public TestItem SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                _selectedItem = value;
                this.DoNotify();
            }
        }

        private TestItem _selectedItem2;

        public TestItem SelectedItem2
        {
            get { return _selectedItem2; }
            set
            {
                _selectedItem2 = value;
                this.DoNotify();
            }
        }

        private int _selectedIndex;

        public int SelectedIndex
        {
            get { return _selectedIndex; }
            set
            {
                _selectedIndex = value;
                this.DoNotify();
            }
        }

        private ListCollectionView _dataView;

        public ListCollectionView DataView
        {
            get { return _dataView; }
            set
            {
                _dataView = value;
                this.DoNotify();
            }
        }

        private ListCollectionView _dataView2;

        public ListCollectionView DataView2
        {
            get { return _dataView2; }
            set
            {
                _dataView2 = value;
                this.DoNotify();
            }
        }

        private bool Filter(object sender)
        {
            if (sender is TestItem item) // YourItemType 是你的项的类型
            {
                return item.Type == "测试"; // 根据某个属性值判断是否显示
            }
            return false;
        }

        private bool _station1Checked;

        public bool Station1Checked
        {
            get { return _station1Checked; }
            set
            {
                _station1Checked = value;
                this.DoNotify();
            }
        }

        private bool _station2Checked;

        public bool Station2Checked
        {
            get { return _station2Checked; }
            set
            {
                _station2Checked = value;
                this.DoNotify();
            }
        }

        public Config Config { get; set; }

        public HomeViewModel()
        {
            PassNgCountClearCommand = new CommandBase(PassNgCountClear);
            StartCommand = new CommandBase(Start);
            StepTestCommand = new CommandBase(StepTest);
            ResetCommand = new CommandBase(Reset);
            LoadCommand = new CommandBase(Load);
            try
            {
                SN1 = "";
                SN2 = "";
                Result = null;
                Counter = Counter.Load();
                OKCount = Counter.OkCount;
                NGCount = Counter.NgCount;
                PointLabel = chartPoint =>
                string.Format("{0} ({1:P})", chartPoint.Y, chartPoint.Participation);

                PointLabel = chartPoint =>
                      string.Format("{0} ({1:P})", chartPoint.Y, chartPoint.Participation);

                Config.ParseExcelFile();
                Global.JFlashExePath = Config.Params["JFlashExePath"];
                JLink.LogEvent = new Action<string>((log) => { Log = $"{log}"; });

#if JQ8931314
                Global.IsJq8931314 = Visibility.Visible;
                Global.Jq1314Config = new ExcelTool();
                Global.Jq1314Config.ParseFile(Global.Jq1314ConfigFile, "config");
                Log = "JQ8931314配置加载完成";

#endif

                IsWriteFlash = false;
                LoadTestConfig();
                InitDevice();

                //DataView = new ListCollectionView(Data);
                //DataView.Filter = Filter;
                //DataView2 = new ListCollectionView(Data2);
                //DataView2.Filter = Filter;

                Log = "初始化完成";
            }
            catch (Exception ex)
            {
                Mylog.Error(ex, ex.Message);
                Log = ex.Message + "!";
            }
        }

        private void Load(object obj)
        {
            if (Global.IsConfigChanged)
            {
                ReloadTestFile();
                Global.IsConfigChanged = false;
                if (Station1Checked)
                {
                    SNInputAction?.Invoke(1);
                }
                else
                {
                    SNInputAction.Invoke(2);
                }
            }
        }

        private int snLength = 0;

        private void ReloadTestFile()
        {
            try
            {
                TestConfigFilePath = Config.Params["测试配置路径"];

                LoadTestConfig();
                Station1Checked = Config.Params["工位1是否启用"] == "1";
                Station2Checked = Config.Params["工位2是否启用"] == "1";

                snLength = int.Parse(Config.Params["SN长度"]);
                //Global.ListJLinkSN.Clear();
                //Global.ListJLinkSN.Add(TestModule.GetParams("JLinkSN1"));
                //Global.ListJLinkSN.Add(TestModule.GetParams("JLinkSN2"));
                Global.ProductName = TestModule.GetParams("产品名称");

                Log = "测试配置加载完成";
            }
            catch (Exception ex)
            {
                Log = ex.Message + "!";
            }
        }

        private bool isReseting = false;

        private void ResetData(int station)
        {
            if (station == 0)
            {
                foreach (var item in Data)
                {
                    item.Result = null;
                    item.Message = "";
                }
            }
            else
            {
                foreach (var item in Data2)
                {
                    item.Result = null;
                    item.Message = "";
                }
            }
        }

        private void Reset(object obj)
        {
            Task.Run(() =>
            {
                if (isReseting)
                {
                    return;
                }

                if (Global.IsBusy)
                {
                    Log = "正在执行其他操作,请完成后再尝试!";
                    return;
                }
                Global.IsBusy = true;
                isReseting = true;
                try
                {
                    Result = null;
                    Result2 = null;
                    SetSysLed(0);
                    if (Station1Checked)
                    {
                        Global.List16ChPQW[0].SetDO((int)PQW16DODefine.DC24, false);
                        Global.List16ChPQW[0].SetDO((int)PQW16DODefine.RuPower, false);
                        Global.List16ChPQW[0].SetDO((int)PQW16DODefine.It6301CH1, false);
                        Global.List16ChPQW[0].SetDO((int)PQW16DODefine.It6302CH2, false);
                        Global.List16ChPQW[0].SetDO((int)PQW16DODefine.It6302CH3, false);
                        Global.List16ChPQW[0].SetDO((int)PQW16DODefine.JqInnerPower, false);
                        Global.List16ChPQW[0].SetDO((int)PQW16DODefine.JqComConnect, false);
                        Global.List16ChPQW[0].SetDO((int)PQW16DODefine.ReversePower1, false);
                        Global.List16ChPQW[0].SetDO((int)PQW16DODefine.ReversePower2, false);
                        Global.List16ChPQW[0].SetDO((int)PQW16DODefine.ModelFlash, false);
                        Global.List16ChPQW[0].SetDO((int)PQW16DODefine.FlashErase, false);
                        Global.List8ChPQW[0].SetDO((int)PQW8DODefine.KA1415, false);
                        Global.List8ChPQW[0].SetDO((int)PQW8DODefine.KA1617, false);
                        ResetData(0);
                    }
                    if (Station2Checked)
                    {
                        Global.List16ChPQW[1].SetDO((int)PQW16DODefine.DC24, false);
                        Global.List16ChPQW[1].SetDO((int)PQW16DODefine.RuPower, false);
                        Global.List16ChPQW[1].SetDO((int)PQW16DODefine.It6301CH1, false);
                        Global.List16ChPQW[1].SetDO((int)PQW16DODefine.It6302CH2, false);
                        Global.List16ChPQW[1].SetDO((int)PQW16DODefine.It6302CH3, false);
                        Global.List16ChPQW[1].SetDO((int)PQW16DODefine.JqInnerPower, false);
                        Global.List16ChPQW[1].SetDO((int)PQW16DODefine.JqComConnect, false);
                        Global.List16ChPQW[1].SetDO((int)PQW16DODefine.ReversePower1, false);
                        Global.List16ChPQW[1].SetDO((int)PQW16DODefine.ReversePower2, false);
                        Global.List16ChPQW[1].SetDO((int)PQW16DODefine.ModelFlash, false);
                        Global.List16ChPQW[1].SetDO((int)PQW16DODefine.FlashErase, false);
                        Global.List8ChPQW[1].SetDO((int)PQW8DODefine.KA1415, false);
                        Global.List8ChPQW[1].SetDO((int)PQW8DODefine.KA1617, false);
                        ResetData(1);
                    }

                    CylinderOrigin();
                    if (Station1Checked)
                    {
                        SNInputAction?.Invoke(1);
                    }
                    else
                    {
                        SNInputAction.Invoke(2);
                    }
                    SN1 = "";
                    SN2 = "";
                    Log = "复位完成";
                }
                catch (Exception ex)
                {
                    Log = ex.Message + "!";
                }
                finally
                {
                    isReseting = false;
                    Global.IsBusy = false;
                }
            });
        }

        private void StepTest(object obj)
        {
            if (Global.IsBusy)
            {
                Log = "正在执行其他操作,请完成后再尝试!";
                return;
            }
            Global.IsBusy = true;
            try
            {
                Task.Run(() =>
                {
                    int staIndex = int.Parse(obj.ToString());
                    if (Global.User.UserLevel == UserLevel.Operator)
                    {
                        Log = "无操作权限，请登录管理员后操作!";
                        return;
                    }
                    TestItem[] test;
                    if (staIndex == 0)
                    {
                        Global.IP20Factorys[staIndex].SN = SN1;
                        test = Data.Where(x => x.GroupNo == SelectedItem.GroupNo).ToArray();
                    }
                    else
                    {
                        Global.IP20Factorys[staIndex].SN = SN2;
                        test = Data2.Where(x => x.GroupNo == SelectedItem2.GroupNo).ToArray();
                    }

                    for (int i = 0; i < test.Count(); i++)
                    {
                        Log = $"工位{staIndex + 1}{test[i].Desc}";
                        try
                        {
                            test[i].Result = test[i].Excute(test[i]);
                        }
                        catch (Exception ex)
                        {
                            Log = ex.Message + "!";
                        }

                        Thread.Sleep(100);
                    }
                });
            }
            catch (Exception ex)
            {
                Log = ex.Message + "!";
            }
            finally
            {
                Global.IsBusy = false;
            }
        }

        private bool isTesting = false;

        /// <summary>
        /// 0 黄灯 1 红灯 2 绿灯
        /// </summary>
        private void SetSysLed(int status)
        {
            switch (status)
            {
                case 0:
                    Global.List16ChPQW[0].SetDO((int)PQW16DODefine.Yellow, true);
                    Global.List16ChPQW[0].SetDO((int)PQW16DODefine.Red, false);
                    Global.List16ChPQW[0].SetDO((int)PQW16DODefine.Green, false);
                    break;

                case 1:
                    Global.List16ChPQW[0].SetDO((int)PQW16DODefine.Yellow, false);
                    Global.List16ChPQW[0].SetDO((int)PQW16DODefine.Red, true);
                    Global.List16ChPQW[0].SetDO((int)PQW16DODefine.Green, false);
                    break;

                case 2:
                    Global.List16ChPQW[0].SetDO((int)PQW16DODefine.Yellow, false);
                    Global.List16ChPQW[0].SetDO((int)PQW16DODefine.Red, false);
                    Global.List16ChPQW[0].SetDO((int)PQW16DODefine.Green, true);
                    break;

                default:
                    break;
            }
        }

        private void WriteLogToFile(List<string> content, string jobId, string serialNumber, bool isSuccess)
        {
            try
            {
                // 1. 确定基础路径
                string basePath = Config.Params["测试报告路径"];

#if  JQ8931314
                if (_isWriteFlash == true)
                {
                    basePath = basePath + "\\burn";
                }

#endif

                // 2. 创建当天日期格式的文件夹（yyyy-MM-dd）
                string dateFolder = DateTime.Now.ToString("yyyy-MM-dd");
                string fullPath = basePath;
                //string fullPath = Path.Combine(basePath, dateFolder);

                // 如果目录不存在则创建
                if (!Directory.Exists(fullPath))
                {
                    Directory.CreateDirectory(fullPath);
                }

                // 3. 生成文件名
                string status = isSuccess ? "OK" : "NG";
                string timestamp = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss");
                //string fileName = $"_{jobId}_SN({serialNumber})_{status}_{timestamp}.html";
                string fileName = $"{serialNumber}_{timestamp}_{status}.txt";

                // 4. 完整文件路径
                string filePath = Path.Combine(fullPath, fileName);

                // 5. 写入文件
                File.WriteAllLines(filePath, content, Encoding.UTF8);

                Console.WriteLine($"日志已成功写入：{filePath}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"写入日志时出错：{ex.Message}");
            }
        }

        private static void WriteLogToFileHtml(List<string> content, string jobId, string serialNumber, bool isSuccess)
        {
            try
            {
                // 1. 确定基础路径
                string basePath = Config.Params["测试报告路径"];

                // 2. 创建当天日期格式的文件夹（yyyy-MM-dd）
                string dateFolder = DateTime.Now.ToString("yyyy-MM-dd");
                string fullPath = basePath;
                //string fullPath = Path.Combine(basePath, dateFolder);

                // 如果目录不存在则创建
                if (!Directory.Exists(fullPath))
                {
                    Directory.CreateDirectory(fullPath);
                }

                // 3. 生成文件名
                string status = isSuccess ? "OK" : "NG";
                string timestamp = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss");
                string fileName = $"_{jobId}_SN({serialNumber})_{status}_{timestamp}.html";

                // 4. 完整文件路径
                string filePath = Path.Combine(fullPath, fileName);

                // 5. 写入文件
                File.WriteAllLines(filePath, content, Encoding.UTF8);

                Console.WriteLine($"日志已成功写入：{filePath}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"写入日志时出错：{ex.Message}");
            }
        }

        private void ExcuteTest(int index)
        {
            try
            {
                Stopwatch sw = Stopwatch.StartNew();
                ObservableCollection<TestItem> testData = null;
                if (index == 0)
                {
                    testData = Data;
                    Result = null;
                }
                else
                {
                    testData = Data2;
                    Result2 = null;
                }
                foreach (var item in testData)
                {
                    item.Result = null;
                    item.Message = "";
                }

                StartTime = DateTime.Now;

                foreach (var testItem in testData.Where(x => x.Type == "测试"))
                {
                    TestItem[] test = null;
                    if (index == 0)
                    {
                        SelectedItem = testItem;
                        test = testData.Where(x => x.GroupNo == SelectedItem.GroupNo).ToArray();
                    }
                    else
                    {
                        SelectedItem2 = testItem;
                        test = testData.Where(x => x.GroupNo == SelectedItem2.GroupNo).ToArray();
                    }

                    DateTime singStartTime = DateTime.Now;
                    foreach (var item in test)
                    {
                        if (Global.IsEmgStopSingal)
                        {
                            throw new Exception("急停触发");
                        }
                        if (!item.IsChecked)
                        {
                            continue;
                        }
                        Log = $"[工位{index + 1}] [{item.Desc}]";
                        try
                        {
                            item.Result = item.Excute(item);
                            if (item.Result == false)
                            {
                                if (item.BreakIfErr)
                                {
                                    throw new Exception("NG结束");
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            //Log = $"[工位{index + 1}] [{ex.Message}]!";
                            item.Result = false;
                            //if (item.BreakIfErr)
                            //{
                            throw ex;
                            //}
                            //return;
                        }

                        //Thread.Sleep(50);
                    }
                    DateTime singEndTime = DateTime.Now;
                    testItem.TestTime = (singEndTime - singStartTime).TotalSeconds.ToString() + "s";
                }

                List<string> lines = new List<string>();
                lines.Add($"产品型号:{Global.ProductName}");

                bool stationResult = true;
                foreach (var testItem in testData.Where(x => x.Type == "测试"))
                {
                    if (!testItem.IsChecked)
                    {
                        continue;
                    }
                    string ret;
                    if (testItem.Result is null)
                    {
                        ret = "待测";
                        stationResult = false;
                    }
                    else
                    {
                        if (testItem.Result == true)
                        {
                            ret = "OK";
                        }
                        else
                        {
                            stationResult = false;
                            ret = "NG";
                        }
                    }
                    lines.Add($"{testItem.Desc}:OK条件({testItem.PassCondition}),测试结果({ret}),详情({testItem.Message})");
                }

                // 输出测试报告

                if (stationResult)
                {
                    OKCount++;
                    if (index == 0)
                    {
                        Result = true;
                        WriteLogToFile(lines, Path.GetFileName(Config.Params["测试配置路径"]).Split('.').ToArray()[0], SN1, true);
                    }
                    else
                    {
                        Result2 = true;
                        WriteLogToFile(lines, Path.GetFileName(Config.Params["测试配置路径"]).Split('.').ToArray()[0], SN2, true);
                    }
                }
                else
                {
                    NGCount++;
                    if (index == 0)
                    {
                        Result = false;
                        WriteLogToFile(lines, Path.GetFileName(Config.Params["测试配置路径"]).Split('.').ToArray()[0], SN1, false);
                    }
                    else
                    {
                        Result2 = false;
                        WriteLogToFile(lines, Path.GetFileName(Config.Params["测试配置路径"]).Split('.').ToArray()[0], SN2, false);
                    }
                }

                Log = $"工位{index + 1}测试耗时{(int)sw.Elapsed.TotalSeconds}s";
            }
            catch (Exception ex)
            {
                NGCount++;
                Log = $"[工位{index + 1}][{ex.Message}]!";
                Mylog.Error($"[工位{index + 1}][{ex.Message}]!");
                if (index == 0)
                {
                    TestModule.NeedWaitStation1PowerEnd = false;
                    TestModule.Station1PowerEndEvent?.Set();
                    Result = false;
                    //WriteLogToFile(lines, Path.GetFileName(Config.Params["测试配置路径"]).Split('.').ToArray()[0], SN1, false);
                }
                else
                {
                    TestModule.NeedWaitStation2PowerEnd = false;
                    TestModule.Station2PowerEndEvent?.Set();
                    Result2 = false;
                    //WriteLogToFile(lines, Path.GetFileName(Config.Params["测试配置路径"]).Split('.').ToArray()[0], SN2, false);
                }
            }
            finally
            {
                try
                {
                    Global.IP20Factorys[index].Close();
                }
                catch (Exception ex)
                {
                    Mylog.Error($"[工位{index + 1}][{ex.Message}]!");
                    Log = $"[工位{index + 1}][{ex.Message}]!";
                }
            }
        }

        private void Start(object obj)
        {
            Task.Run(() =>
            {
                if (isTesting)
                {
                    return;
                }

                if (Global.IsBusy)
                {
                    Log = "正在执行其他操作,请完成后再操作!";
                    return;
                }
                if (Global.IsSafeDoorSingal)
                {
                    Log = "安全光栅感应!";
                    return;
                }
                isTesting = true;
                Global.IsBusy = true;
                if (Station1Checked && Station2Checked)
                {
                    TestModule.NeedWaitStation1PowerEnd = true;
                    TestModule.NeedWaitStation2PowerEnd = true;
                    TestModule.Station1PowerEndEvent = new AutoResetEvent(false);
                    TestModule.Station2PowerEndEvent = new AutoResetEvent(false);

                    //Global.IP20FlashEvent = new AutoResetEvent(false);
                }
                else
                {
                    TestModule.NeedWaitStation1PowerEnd = false;
                    TestModule.NeedWaitStation2PowerEnd = false;
                    TestModule.Station1PowerEndEvent = null;
                    TestModule.Station2PowerEndEvent = null;
                    //Global.IP20FlashEvent = null;
                }

                Log = "开始测试";
                try
                {
                    // check sn
                    if (Station1Checked)
                    {
                        if (snLength != SN1.Length)
                        {
                            throw new Exception("工位1SN长度异常");
                        }
                    }
                    if (Station2Checked)
                    {
                        if (snLength != SN2.Length)
                        {
                            throw new Exception("工位2SN长度异常");
                        }
                    }
                    if (Station1Checked && Station2Checked)
                    {
                        if (SN1 == SN2)
                        {
                            throw new Exception("SN重复");
                        }
                    }

                    Global.IP20Factorys[0].SN = SN1;
                    Global.IP20Factorys[1].SN = SN2;
                    Global.MacFull = true;
                    TwinCatTool.Connect();

                    SetSysLed(0);
                    CylinderWork();
                    Task task1 = null;
                    Task task2 = null;
                    if (Station1Checked)
                    {
                        task1 = Task.Run(() => { ExcuteTest(0); });
                    }
                    if (Station2Checked)
                    {
                        task2 = Task.Run(() => { ExcuteTest(1); });
                    }
                    task1?.Wait();
                    task2?.Wait();
                    SN1 = "";
                    SN2 = "";
                    CylinderOrigin();

                    if (!Station1Checked)
                    {
                        Result = true;
                    }
                    if (!Station2Checked)
                    {
                        Result2 = true;
                    }

                    if (Result == true && Result2 == true)
                    {
                        SetSysLed(2);
                    }
                    else
                    {
                        SetSysLed(1);
                    }
                    TwinCatTool.Close();
                }
                catch (Exception ex)
                {
                    Log = ex.Message + "!";
                }
                finally
                {
                    Global.IsBusy = false;
                    isTesting = false;
                    SN1 = "";
                    SN2 = "";
                    if (Station1Checked)
                    {
                        SNInputAction?.Invoke(1);
                    }
                    else
                    {
                        SNInputAction.Invoke(2);
                    }
                    if (!Global.MacFull)
                    {
                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            MessageBox.Show("MAC可用量报警", "警告", MessageBoxButton.OK);
                        });
                    }
                }
            });
        }

        private void CylinderWork()
        {
            if (Global.IsSafeDoorSingal)
            {
                throw new Exception("安全光栅感应");
            }
            if (Global.IsEmgStopSingal)
            {
                throw new Exception("设备急停");
            }
            // 气缸到位
            cylinderWorkManualResetEvent.Reset();
            Global.List16ChPQW[0].SetDO((int)PQW16DODefine.CylinderMove, true);

            if (!cylinderWorkManualResetEvent.WaitOne(8000))
            {
                throw new Exception("气缸到位超时");
            }
        }

        private void CylinderOrigin()
        {
            if (Global.IsSafeDoorSingal)
            {
                throw new Exception("安全光栅感应");
            }
            if (Global.IsEmgStopSingal)
            {
                throw new Exception("设备急停");
            }
            // 气缸到位
            cylinderOriginManualResetEvent.Reset();
            Global.List16ChPQW[0].SetDO((int)PQW16DODefine.CylinderMove, false);

            if (!cylinderOriginManualResetEvent.WaitOne(8000))
            {
                throw new Exception("气缸复位超时");
            }
        }

        private void InitDevice()
        {
            // led 采集卡
            {
                Global.JX1000 = new();
                Global.JX1000.Connect(Config.Params["JX1000串口"]);
            }

            //工位1 3通道程控电源
            {
                IT6302 power = new IT6302("工位1IT6302");
                power.Connect(Config.Params["工位1程控电源IT6302串口"], 38400);
                power.SetRemote();
                Global.ListIT6302.Add(power);
            }
            // 工位2 3通道程控电源
            {
                IT6302 power = new IT6302("工位2IT6302");
                power.Connect(Config.Params["工位2程控电源IT6302串口"], 38400);
                power.SetRemote();
                Global.ListIT6302.Add(power);
            }
            // 工位1 电压采集卡 电流采集卡 RU电源 //温度采集卡
            {
                SerialBase serial = new SerialBase();
                serial.Connect(Config.Params["工位1RS485总线1组串口"], 38400);

                ZS_AnalogInput voltageCard1 = new ZS_AnalogInput(serial, 1, 8, "工位1电压采集卡1(8CH)");
                Global.ListVoltageCards.Add(voltageCard1);

                ZS_AnalogInput voltageCard2 = new ZS_AnalogInput(serial, 2, 8, "工位1电压采集卡2(8CH)");
                Global.ListVoltageCards.Add(voltageCard2);

                ZS_AnalogInput voltageCard3 = new ZS_AnalogInput(serial, 4, 3, "工位1电压采集卡3(3CH)");
                Global.ListVoltageCards.Add(voltageCard3);

                ZS_AnalogInput currentCard1 = new ZS_AnalogInput(serial, 5, 8, "工位1PNP电流采集卡1(8CH)");
                Global.ListCurrentCards.Add(currentCard1);

                ZS_AnalogInput currentCard2 = new ZS_AnalogInput(serial, 6, 8, "工位1PNP电流采集卡2(8CH)");
                Global.ListCurrentCards.Add(currentCard2);

                ZS_AnalogInput currentCard3 = new ZS_AnalogInput(serial, 7, 3, "工位1PNP电流采集卡3(3CH)");
                Global.ListCurrentCards.Add(currentCard3);

                ZS_AnalogInput currentCard4 = new ZS_AnalogInput(serial, 9, 8, "工位1NPN电流采集卡1(8CH)");
                Global.ListCurrentCards.Add(currentCard4);

                ZS_AnalogInput currentCard5 = new ZS_AnalogInput(serial, 10, 8, "工位1NPN电流采集卡1(8CH)");
                Global.ListCurrentCards.Add(currentCard5);

                RU_12_3040 ru = new RU_12_3040(serial, 3, "工位1RU系列电源");
                Global.ListRUPower.Add(ru);

                Global.TempCard = new ZS_TemperatureCard(serial, 8, 4, "温度采集卡");
            }
            // 工位2 电压采集卡 电流采集卡 RU电源
            {
                SerialBase serial = new SerialBase();
                serial.Connect(Config.Params["工位2RS485总线1组串口"], 38400);

                ZS_AnalogInput voltageCard1 = new ZS_AnalogInput(serial, 1, 8, "工位2电压采集卡1(8CH)");
                Global.ListVoltageCards.Add(voltageCard1);

                ZS_AnalogInput voltageCard2 = new ZS_AnalogInput(serial, 2, 8, "工位2电压采集卡2(8CH)");
                Global.ListVoltageCards.Add(voltageCard2);

                ZS_AnalogInput voltageCard3 = new ZS_AnalogInput(serial, 4, 3, "工位2电压采集卡3(3CH)");
                Global.ListVoltageCards.Add(voltageCard3);

                ZS_AnalogInput currentCard1 = new ZS_AnalogInput(serial, 5, 8, "工位2PNP电流采集卡1(8CH)");
                Global.ListCurrentCards.Add(currentCard1);

                ZS_AnalogInput currentCard2 = new ZS_AnalogInput(serial, 6, 8, "工位2PNP电流采集卡2(8CH)");
                Global.ListCurrentCards.Add(currentCard2);

                ZS_AnalogInput currentCard3 = new ZS_AnalogInput(serial, 7, 3, "工位2PNP电流采集卡3(3CH)");
                Global.ListCurrentCards.Add(currentCard3);

                ZS_AnalogInput currentCard4 = new ZS_AnalogInput(serial, 9, 8, "工位2NPN电流采集卡1(8CH)");
                Global.ListCurrentCards.Add(currentCard4);

                ZS_AnalogInput currentCard5 = new ZS_AnalogInput(serial, 10, 8, "工位2NPN电流采集卡1(8CH)");
                Global.ListCurrentCards.Add(currentCard5);

                RU_12_3040 ru = new RU_12_3040(serial, 3, "工位1RU系列电源");
                Global.ListRUPower.Add(ru);
            }
            // 工位1 pqw IO卡 16+8 通道
            {
                SerialBase serial = new SerialBase();
                serial.Connect(Config.Params["工位1RS485总线2组串口"], 38400);

                PQW_IO pqw16 = new PQW_IO(serial, 1, "工位1pqw16通道IO");
                pqw16.DOCount = 16;
                pqw16.DICount = 16;
                Global.List16ChPQW.Add(pqw16);
                PQW_IO pqw8 = new PQW_IO(serial, 2, "工位1pqw8通道IO");
                pqw8.DOCount = 8;
                pqw8.DICount = 0;
                Global.List8ChPQW.Add(pqw8);
            }
            // 工位2 pqw IO卡 16+8 通道
            {
                SerialBase serial = new SerialBase();
                serial.Connect(Config.Params["工位2RS485总线2组串口"], 38400);

                PQW_IO pqw16 = new PQW_IO(serial, 1, "工位2pqw16通道IO");
                pqw16.DOCount = 16;
                pqw16.DICount = 16;
                Global.List16ChPQW.Add(pqw16);
                PQW_IO pqw8 = new PQW_IO(serial, 2, "工位2pqw8通道IO");
                pqw8.DOCount = 8;
                pqw8.DICount = 0;
                Global.List8ChPQW.Add(pqw8);
            }
            // 工位1 电子负载
            {
                DL3021A dl = new DL3021A("工位1电子负载");
                dl.Connect(Config.Params["工位1电子负载VISA地址"]);
                Global.ListDL3021A.Add(dl);
            }
            // 工位2 电子负载
            {
                DL3021A dl = new DL3021A("工位2电子负载");
                dl.Connect(Config.Params["工位2电子负载VISA地址"]);
                Global.ListDL3021A.Add(dl);
            }

            // 稀微 烧录器
            {
                for (int j = 0; j < 3; j++)
                {
                    try
                    {
                        for (int i = 0; i < 2; i++)
                        {
                            XiWeiFlash flash = new XiWeiFlash();
                            flash.DeviceName = $"工位{i + 1}烧录器";

                            flash.Connect(Config.Params[$"XiWeiPort{i + 1}"], 115200);
                            Thread.Sleep(100);
                            flash.LogEvent += (obj) =>
                            {
                                Mylog.Debug($"{flash.DeviceName}[{obj}]");
                            };
                            flash.GetFlashCount();
                            flash.GetAllFlashInfo();
                            Global.ListXiWeiFlash.Add(flash);

                            flash.LogEvent += (obj) =>
                            {
                                Log = $"[{obj}]";
                            };
                        }
                        break;
                    }
                    catch (Exception ex)
                    {
                        if (j == 2)
                        {
                            throw ex;
                        }
                    }
                }
            }

            Task.Run(() =>
            {
                while (true)
                {
                    try
                    {
                        Global.List16ChPQW[0].GetDI();
                        Thread.Sleep(100);
                        Global.List16ChPQW[0].GetDO();
                        Thread.Sleep(100);

                        Global.List8ChPQW[0].GetDO();
                        Thread.Sleep(100);
                    }
                    catch (Exception ex)
                    {
                        Mylog.Error(ex);
                        Log = ex.Message + "!";
                    }
                }
            });
            Task.Run(() =>
            {
                while (true)
                {
                    try
                    {
                        Global.List16ChPQW[1].GetDI();
                        Thread.Sleep(100);
                        Global.List16ChPQW[1].GetDO();
                        Thread.Sleep(100);
                        //Global.List8ChPQW[1].GetDI();
                        //Thread.Sleep(100);
                        Global.List8ChPQW[1].GetDO();
                        Thread.Sleep(100);
                    }
                    catch (Exception ex)
                    {
                        Mylog.Error(ex);
                        Log = ex.Message + "!";
                    }
                }
            });
            Global.List16ChPQW[0].DIUpdateEvent += DIUpdatEvent_sta0_16ch;
            {
                IP20Factory factory = new IP20Factory(byte.Parse(Config.Params["IP20耦合器测试工位1串口"]));

                factory.WiteType = (FactoryWriteType)int.Parse(Config.Params["IP20耦合器写入类型"]);
                factory.ComApi = (FactoryCommunicationApi)int.Parse(Config.Params["IP20耦合器通信模式"]);
                factory.SN = "";
                factory.ActionNotify += ((log) => { Log = $"[工位1] {log}"; });
                Global.IP20Factorys.Add(factory);
            }
            {
                IP20Factory factory = new IP20Factory(byte.Parse(Config.Params["IP20耦合器测试工位2串口"]));
                factory.WiteType = (FactoryWriteType)int.Parse(Config.Params["IP20耦合器写入类型"]);
                factory.ComApi = (FactoryCommunicationApi)int.Parse(Config.Params["IP20耦合器通信模式"]);
                factory.SN = "";
                factory.ActionNotify += ((log) => { Log = $"[工位2] {log}"; });
                Global.IP20Factorys.Add(factory);
            }
            Global.IP20Ports.Add("COM" + Config.Params["IP20耦合器测试工位1串口"]);
            Global.IP20Ports.Add("COM" + Config.Params["IP20耦合器测试工位2串口"]);
        }

        private void DIUpdatEvent_sta1_8ch(byte[] obj)
        {
            //throw new NotImplementedException();
        }

        private void DIUpdatEvent_sta0_8ch(byte[] obj)
        {
            //throw new NotImplementedException();
        }

        private void DIUpdatEvent_sta1_16ch(byte[] obj)
        {
            //throw new NotImplementedException();
        }

        private bool GetBit(byte[] data, int bitIndex)
        {
            return (data[bitIndex / 8] & (1 << bitIndex % 8)) > 0;
        }

        private void DIUpdatEvent_sta0_16ch(byte[] obj)
        {
            if (GetBit(obj, (int)PQW16DIDefine.Start))
            {
                Start(null);
            }

            if (!GetBit(obj, (int)PQW16DIDefine.EmgStop))
            {
                Global.IsEmgStopSingal = true;
                TestModule1.IsBreak = true;
                TestModule2.IsBreak = true;
            }
            else
            {
                Global.IsEmgStopSingal = false;
                TestModule1.IsBreak = false;
                TestModule2.IsBreak = false;
            }
            if (!GetBit(obj, (int)PQW16DIDefine.Safe))
            {
                Global.IsSafeDoorSingal = true;
            }
            else
            {
                Global.IsSafeDoorSingal = false;
            }
            if (GetBit(obj, (int)PQW16DIDefine.Reset))
            {
                Reset(null);
            }
            if (GetBit(obj, (int)PQW16DIDefine.CylinderOrigin))
            {
                cylinderOriginManualResetEvent?.Set();
            }
            if (GetBit(obj, (int)PQW16DIDefine.CylinderWork))
            {
                cylinderWorkManualResetEvent?.Set();
            }
        }

        private ManualResetEvent cylinderOriginManualResetEvent = new(false);
        private ManualResetEvent cylinderWorkManualResetEvent = new(false);

        private void StartAction()
        {
            Start(null);
        }

        internal Action<int> SNInputAction;

        private TestModule TestModule1;
        private TestModule TestModule2;

        private void LoadTestConfig()
        {
            string path = Config.Params["测试配置路径"];

#if JQ8931314
            var directory = Path.GetDirectoryName(Config.Params["测试配置路径"]);
            var pat = Path.GetFileName(Config.Params["测试配置路径"]).Substring(0, 7) + (_isWriteFlash == true ? "_burn" : "_fct");
            var find = SearchFiles(directory, pat);

            if (find.Count == 1)
            {
                path = find[0];
            }
            else if (find.Count == 0)
            {
                throw new Exception($"未找到文件{pat}*");
            }
            else
            {
                throw new Exception($"找到多个文件{pat}*");
            }

#endif
            TestConfigFilePath = path;
            Data = new ObservableCollection<TestItem>();
            Data2 = new ObservableCollection<TestItem>();

            TestModule1 = new TestModule(0);
            TestModule2 = new TestModule(1);
            TestModule1.ParseExcelFile(path);
            TestModule2.ParseExcelFile(path);
            TestModule1.ActionSetLog = new Action<string>((log) => { Log = $"[工位1] {log}"; });
            TestModule2.ActionSetLog = new Action<string>((log) => { Log = $"[工位2] {log}"; });
            foreach (var item in TestModule1.TestItems)
            {
                Data.Add(item);
            }
            foreach (var item in TestModule2.TestItems)
            {
                Data2.Add(item);
            }
            DataView = new ListCollectionView(Data);
            DataView.Filter = Filter;
            DataView2 = new ListCollectionView(Data2);
            DataView2.Filter = Filter;
        }

        private void PassNgCountClear(object obj)
        {
            OKCount = 0;
            NGCount = 0;
        }

        private DateTime StartTime { get; set; }
        private DateTime EndTime { get; set; }

        public CommandBase PassNgCountClearCommand { get; set; }
        public CommandBase StartCommand { get; set; }
        public CommandBase StepTestCommand { get; set; }
        public CommandBase ResetCommand { get; set; }
        public CommandBase LoadCommand { get; set; }
    }
}